﻿using System;
using CcrFlows.Core;
using Microsoft.Ccr.Core;

namespace SampleFlow
{
    class Program
    {
        static void Main()
        {
            Flow<Parameter, int> flow = 
                new ForkedFlow<Parameter>()
                    .Do<Datacontainer, Parameter>(
                        new ForkedFlow<Parameter, Parameter, string>((p, pp, ps) => { pp.Post(p); ps.Post(p.Query); })
                                .Do<bool, string>(Validiere,
                                                  FlowHandlers.Copy<string>())
                            .Join<string>((b, s, ps) => ps.Post(s))
                            .Do<Datacontainer>(LadeDaten),
                        Flow<Parameter>.Copy())
                .Join<Tuple<Datacontainer, Parameter>>((dc, p, pt) => pt.Post(new Tuple<Datacontainer, Parameter>(dc, p)))
                .Do<Tuple<Datacontainer, int>>(Aktualisiere)
                .Fork<Datacontainer, int>((tp, pdc, pi) => { pdc.Post(tp.Item0); pi.Post(tp.Item1); })
                    .Do<bool, int>(SpeichereDaten,
                                   FlowHandlers.Copy<int>())
                .Join<int>((b, i, pi)=>pi.Post(i));

            flow.Input.Post(new Parameter {Payload = "payload", Query = "query"});

            flow.Receive(r => Console.WriteLine("===result {0}", r));

            Console.ReadLine();
        }

        static void Validiere(Parameter p, Port<bool> output)
        {
            Console.WriteLine("validiere: {0}", p.Payload);
            output.Post(true);
        }

        static void LadeDaten(string query, Port<Datacontainer> output)
        {
            Console.WriteLine("laden: {0}", query);
            output.Post(new Datacontainer{Query = query + ".geladen"});
        }

        static void Aktualisiere(Tuple<Datacontainer, Parameter> input, Port<Tuple<Datacontainer, int>> output)
        {
            Console.WriteLine("aktualisieren: data: {0}, payload:{1}", input.Item0.Query, input.Item1.Payload);
            input.Item0.Query += ".aktualisiert";
            output.Post(new Tuple<Datacontainer, int>(input.Item0, DateTime.Now.Second));
        }

        static void SpeichereDaten(Datacontainer dc, Port<bool> output)
        {
            Console.WriteLine("speichern: {0}", dc.Query);
            output.Post(true);
        }
    }

    class Parameter
    {
        public string Query;
        public string Payload;
    }

    class Datacontainer
    {
        public string Query;
    }
}
